import { IStageAssetsInfo } from "babylon-lib/base/stage";
import { Scene } from "@babylonjs/core/scene";
import { Camera } from "@babylonjs/core/Cameras/camera";
import { Light } from "@babylonjs/core/Lights/light";
import { RawAssetsUrl, RawData } from "../raw-assets-info";
import { GenerateComponent } from './default-stage-components/generate-component';
import { ILoose } from "babylon-lib/tool/utils";
import { AbstractAssetTaskInfo, AudioTaskInfo, GLTFMeshTaskInfo, CubeTextureTaskInfo, TextureTaskInfo } from "babylon-lib/loader/asset-task-info";
import * as Data from '../data/data';
import { IActiveDefaultVRExperienceOptions } from 'babylon-lib/xr/vr-container';
import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { SEPARATE_NO_ROTATE_HANDEDNESS_CONFIGURATION } from "babylon-lib/xr/vr-motion/vr-motion-movement";
import { XRStage } from "babylon-lib/base/xr-stage";
import { FreezeCamera } from 'babylon-lib/misc/freeze-camera';
import { RenderOrder } from "babylon-lib/misc/render-order";
import { ProgressManager } from "./default-stage-components/progress-manager";
import { NotePanel } from "../ui/note-panel";
import { SoundManager } from "./default-stage-components/sound-manager";


class DefaultStage extends XRStage {

    protected isProduction(): boolean {
        return Data.isProduction.value;
    }

    protected appName(): string {
        return RawData.appConfig.name;
    }

    protected assetTaskInfos(): ILoose<AbstractAssetTaskInfo> | Array<IStageAssetsInfo> {
        return Object.assign({}, [
            new GLTFMeshTaskInfo(RawAssetsUrl.modelDixing),
            new GLTFMeshTaskInfo(RawAssetsUrl.modelShibing),
            new GLTFMeshTaskInfo(RawAssetsUrl.modelWurenji),
            new GLTFMeshTaskInfo(RawAssetsUrl.modelZhadan),

            new AudioTaskInfo(RawAssetsUrl.soundMusic),
            new AudioTaskInfo(RawAssetsUrl.soundNoteStart),
            new AudioTaskInfo(RawAssetsUrl.soundCountdown),
            new AudioTaskInfo(RawAssetsUrl.soundOver),
            new AudioTaskInfo(RawAssetsUrl.soundExplode),

            new CubeTextureTaskInfo(
                RawAssetsUrl.lightCubePX,
                RawAssetsUrl.lightCubePY,
                RawAssetsUrl.lightCubePZ,
                RawAssetsUrl.lightCubeNX,
                RawAssetsUrl.lightCubeNY,
                RawAssetsUrl.lightCubeNZ,
                0
            ),

            new TextureTaskInfo(RawAssetsUrl.textureYanwu),
            new TextureTaskInfo(RawAssetsUrl.textureMark),
        ]) as unknown as ILoose<AbstractAssetTaskInfo>;
    }

    protected getXROptions(): IActiveDefaultVRExperienceOptions {
        return {
            renderingGroupId: RenderOrder.id(RenderOrder.topName),
            cameraOptions: {
                position: Data.cameraPosition.value,
                target: Data.cameraTarget.value,
                maxZ: 5000,
                minZ: 0.1,
                speed:0,
                detached:true,
            },
            disableTeleportation: true,
        };
    }

    protected generateComponents(scenes: Scene[], cameras: Camera[], lights: Light[]): void {
        /**
         * 自定义
         */
        GenerateComponent.initialize(this);
        this.bindData();
        Data.cameraData.reset(true);
        FreezeCamera.freezePosition(this.mainScene);
    }

    public async reset(): Promise<void> {
        await super.reset();
        /**
         * 自定义
         */
        SoundManager.background.stop();
        Data.rootData.reset();
        Data.cameraData.reset(true);
        FreezeCamera.freezePosition(this.mainScene);
        ProgressManager.reset();
        NotePanel.note();
    }

    public resetSight(): void {
        super.resetSight();
        /**
         * 自定义
         */

    }

    public async changeImmersive(inaction?: boolean | undefined): Promise<void> {
        await super.changeImmersive(inaction);
        /**
         * 自定义
         */
        if (!ProgressManager.started) ProgressManager.start();
    }

    private bindData(): void {
        Data.cameraData.onChange(() => {
            this.mainCamera.position = Data.cameraPosition.value;
            (this.mainCamera as FreeCamera).target = Data.cameraTarget.value;
        });
        Data.gameOn.onChange((o, n) => {
            n ? FreezeCamera.unfreeze() : FreezeCamera.freezePosition(this.mainScene);
            ProgressManager.pause = !n;
        });
    }

}


export { DefaultStage };